package Or

import "C"
import (
	"fmt"
)

var (
	getTableNameSql = func(o, s, t string) string {
		return fmt.Sprintf("SELECT \"TABLE_NAME\" from %v where owner = '%s' %v", o, s, getLikeTable(t))
	}
	getSeqNameSql = func(o, s, t string) string {
		return fmt.Sprintf("SELECT \"SEQUENCE_NAME\" from %v where SEQUENCE_OWNER ='%v' %v", o, s, getLikeSeqName(t))
	}
	getTableExistenceSql = func(o, s, t string) string {
		return fmt.Sprintf("SELECT \"TABLE_NAME\" from %v where owner = '%s' and table_NAME = '%s'", o, s, t)
	}
	getSeqExistenceSql = func(o, s, t string) string {
		return fmt.Sprintf("select \"SEQUENCE_NAME\" from %v where SEQUENCE_OWNER = '%v' AND SEQUENCE_NAME='%v'", o, s, t)
	}
	getSchemaNameSql = func(o, s, t string) string {
		return fmt.Sprintf("SELECT username  FROM %v WHERE username = '%v'", o, s)
	}
	getTableCommentSql = func(o, s, t string) string {
		return fmt.Sprintf("SELECT comments as \"comment\" FROM %v WHERE OWNER = '%v' AND TABLE_NAME='%v'", o, s, t)
	}
	getColumnCommentSql = func(o, s, t string) string {
		return fmt.Sprintf("select COLUMN_NAME as \"columnName\",comments AS \"columnComment\" from %v where owner = '%v' and TABLE_NAME  = '%v' ", o, s, t)
	}
	getTableCharacterSql = func(o, s, t string) string {
		return fmt.Sprintf("select 1+1 from dual")
	}
	getMaxConnections = func(o, s, t string) string {
		return fmt.Sprintf("SELECT value * 2 AS maxAvailableConnection FROM %v WHERE name = 'cpu_count'", o)
	}
	getTableCollationSql = func(o, s, t string) string {
		return fmt.Sprintf("select 1+1 from dual")
	}
	getTableConstraintsSql = func(o, s, t string) string {
		return fmt.Sprintf("SELECT constraint_name as \"name\",search_condition as \"body\" FROM %v WHERE OWNER = '%v' AND table_name = '%v' AND constraint_type = 'C'", o, s, t)
	}
	getSeqBodySql = func(o, s, t string) string {
		return fmt.Sprintf("SELECT 'seq' as \"type\",SEQUENCE_OWNER AS \"schema\",SEQUENCE_NAME AS \"name\",MIN_VALUE AS \"minValue\",MAX_VALUE AS \"maxValue\",INCREMENT_BY AS \"incrementBy\",CYCLE_FLAG AS \"cycleFlag\",ORDER_FLAG AS \"orderFlag\",CACHE_SIZE AS \"cacheSize\",LAST_NUMBER AS \"startValue\" FROM %v WHERE SEQUENCE_OWNER='%v' and SEQUENCE_NAME='%v'", o, s, t)
	}
	getLobColumnSql = func(o, s, t string) string {
		return fmt.Sprintf("select column_name as \"columnName\",data_type as \"columnType\" from %v where OWNER = '%s' AND TABLE_NAME = '%s' AND data_type like '%%LOB%%'", o, s, t)
	}
	getBigColumnSql = func(o, s, t string) string {
		return fmt.Sprintf("select column_name as \"columnName\",data_type as \"columnType\" from %v where OWNER = '%s' AND TABLE_NAME = '%s' and DATA_TYPE = 'VARCHAR2' AND DATA_LENGTH >= 1000", o, s, t)
	}
	getColumnMetaSql = func(o, s, t string) string {
		return fmt.Sprintf("SELECT atc.owner AS \"databaseName\",atc.TABLE_NAME AS \"tableName\",atc.column_name AS \"columnName\",atc.data_type AS \"dataType\",atc.DATA_PRECISION AS \"dataPrecision\",atc.DATA_SCALE AS \"dataScale\",atc.DATA_LENGTH AS \"dataLength\",atc.char_length AS \"charLength\",atc.COLUMN_id AS \"columnSeq\",atc.NULLABLE AS \"isNull\",'' AS \"charset\",(SELECT \"VALUE\" FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER LIKE 'NLS_SORT') AS \"collationName\",atc.DATA_DEFAULT AS \"columnDefault\" FROM %v atc WHERE atc.owner IN ('%v') AND atc.TABLE_NAME IN ('%v') ORDER BY atc.column_id", o, s, t)
	}
	getTableIndexMetaSql = func(o, s, t string) string {
		return fmt.Sprintf("select CO.INDEX_NAME as \"name\", CO.CONSTRAINT_TYPE as \"constraint\" from %v \"CO\" where OWNER IN ('%v') AND TABLE_NAME IN ('%v')", o, s, t)
	}
	getIndexColumnMetaSql = func(o, s, t string) string {
		return fmt.Sprintf("select IC.TABLE_OWNER AS \"databaseName\",IC.TABLE_NAME as \"tableName\",IC.INDEX_NAME AS \"indexName\",IC.COLUMN_POSITION AS \"columnSeq\",IC.COLUMN_NAME as \"columnName\" from \"%v\" \"IC\" WHERE IC.TABLE_OWNER IN ('%v') AND IC.TABLE_NAME IN ('%v') order by IC.INDEX_NAME,IC.COLUMN_POSITION", o, s, t)
	}
	getIndexCategoryMetaSql = func(o, s, t string) string {
		return fmt.Sprintf("SELECT I.TABLE_OWNER AS \"databaseName\",I.TABLE_NAME as \"tableName\",I.INDEX_NAME as \"indexName\",I.UNIQUENESS AS \"nonUnique\",I.DISTINCT_KEYS AS \"cardinality\",I.PARTITIONED AS \"indexCategory\" FROM \"%v\" \"I\" WHERE I.TABLE_OWNER IN ('%v') AND I.TABLE_NAME IN ('%v')", o, s, t)
	}
	getColumnDistinctMetaSql = func(o, s, t string) string {
		return fmt.Sprintf("SELECT COLUMN_NAME AS \"columnName\",NUM_DISTINCT AS \"columnDistinct\" FROM %v WHERE OWNER = '%v' AND table_name = '%v'", o, s, t)
	}
	getTablePartitionTypeMetaSql = func(o, s, t string) string {
		return fmt.Sprintf("SELECT PARTITIONING_TYPE || ',' || SUBPARTITIONING_TYPE AS \"partitionType\" FROM %v WHERE OWNER='%v' AND TABLE_NAME='%v'", o, s, t)
	}
	getTablePartitionSumMetaSql = func(o, s, t string) string {
		return fmt.Sprintf("SELECT SUM(DECODE(COMPOSITE,'YES',SUBPARTITION_COUNT,1)) AS \"sum\" FROM %v WHERE TABLE_OWNER='%v' AND TABLE_NAME = '%v'", o, s, t)
	}
	getTablePartitionRuleMetaSql = func(o, s, t string) string {
		return fmt.Sprintf("SELECT C.PARTITION_NAME AS \"partName\",C.SUBPARTITION_COUNT AS \"subSum\",C.PARTITION_POSITION AS \"seq\",C.HIGH_VALUE AS \"rules\" FROM %v C WHERE C.TABLE_OWNER = '%v' AND C.TABLE_NAME = '%v' order by C.PARTITION_POSITION ", o, s, t)
	}
	getTableSubPartitionRuleMetaSql = func(o, s, t string) string {
		return fmt.Sprintf("SELECT C.PARTITION_NAME AS \"partName\",C.SUBPARTITION_NAME AS \"subPartName\",C.SUBPARTITION_POSITION AS \"seq\",C.HIGH_VALUE AS \"rules\" \n FROM %v C \n WHERE C.TABLE_OWNER = '%v' AND C.TABLE_NAME = '%v' order by C.SUBPARTITION_POSITION ", o, s, t)
	}
	getTablePartitionMethMetaSql = func(o, s, t string) string {
		return fmt.Sprintf("SELECT C.PARTITIONING_TYPE AS \"first\",C.SUBPARTITIONING_TYPE AS \"sub\" FROM %v C \n WHERE C.OWNER = '%v' AND C.TABLE_NAME = '%v'", o, s, t)
	}
	getTablePartitionColMetaSql = func(o, s, t string) string {
		return fmt.Sprintf("SELECT C.COLUMN_NAME AS \"partColumn\" FROM %v C \n WHERE C.OWNER = '%v' AND C.NAME = '%v' order by column_position", o, s, t)
	}
	getTableSubPartitionColMetaSql = func(o, s, t string) string {
		return fmt.Sprintf("SELECT C.COLUMN_NAME AS \"partColumn\" FROM %v C WHERE C.OWNER = '%v' AND C.NAME = '%v' order by column_position", o, s, t)
	}
	getStringValueCompareSql = func(o, s, t string) string {
		return fmt.Sprintf("SELECT C.COLUMN_NAME AS \"partColumn\" FROM %v C WHERE C.OWNER = '%v' AND C.NAME = '%v' order by column_position", o, s, t)
	}
	getFullRowsSizeSql = func(o, s, t string) string {
		return fmt.Sprintf("select num_rows as \"tableRows\" from %v where owner='%s' and table_name='%s'", o, s, t)
	}
	getFullAvgRowsSizeSql = func(o, s, t string) string {
		return fmt.Sprintf("select nvl(round(sum(avg_row_len)/count(1),0),0) AS \"AvgRowsSize\" from %v where owner = '%v' and table_name = '%v' group by table_name", o, s, t)
	}
	getFullIndexSizeMBSql = func(o, s, t string) string {
		return fmt.Sprintf("SELECT ROUND( SUM( bytes ) / 1048576, 2 ) AS \"indexSizeMB\" FROM DBA_SEGMENTS WHERE OWNER = '%v' AND SEGMENT_NAME IN ( SELECT INDEX_NAME FROM %v WHERE TABLE_OWNER = '%v' AND TABLE_NAME = '%v')", s, o, s, t)
	}
	getFullDataSizeMBSql = func(o, s, t string) string {
		return fmt.Sprintf("SELECT ROUND( SUM( bytes ) / 1048576, 2 ) AS \"dataSizeMB\" FROM DBA_SEGMENTS WHERE owner = '%v' AND (SEGMENT_NAME LIKE 'SYS_LOB' || ( SELECT LPAD ( OBJECT_ID, 10, 0 ) FROM %v WHERE owner = '%v' AND OBJECT_NAME = '%v' AND object_type = 'TABLE' ) OR segment_name = '%v') ", s, o, s, t, t)
	}
	getFullTableScnSql = func(o, s, t string) string {
		return fmt.Sprintf("SELECT CURRENT_SCN FROM %v", o)
	}
)

var (
	createSeqBodySql = func(s, t, mi, ma, in, st, ca, or, cy string) string {
		return fmt.Sprintf(
			"CREATE SEQUENCE \"%v\".\"%v\" \n"+
				"\t MINVALUE %v \n"+
				"\t MAXVALUE %v \n"+
				"\t INCREMENT BY %v \n"+
				"\t START WITH %v \n "+
				"\t %v %v %v ; \n", s, t, mi, ma, in, st, ca, or, cy)
	}
	dropSeqSql = func(s, t string) string {
		return fmt.Sprintf("DROP SEQUENCE IF EXISTS \"%v\".\"%v\"", s, t)
	}
	dropTableSql = func(s, t string) string {
		return fmt.Sprintf("BEGIN\n        "+
			"EXECUTE IMMEDIATE 'DROP TABLE %v.%v';\n    "+
			"EXCEPTION\n        "+
			"WHEN OTHERS THEN\n            "+
			"IF SQLCODE != -942 THEN\n                "+
			"RAISE;\n            "+
			"END IF;\n    END;", s, t)
	}
	renameTableSql = func(s, t, ss, tt string) string {
		return fmt.Sprintf("ALTER TABLE \"%v\".\"%v\" RENAME TO \"%v\".\"%v\"", s, t, ss, tt)
	}
	createDatabaseSql = func(s string) string {
		return fmt.Sprintf("CREATE USER IF NOT EXISTS `%v`", s)
	}
	likeTableSql = func(s, t, ss, tt string) string {
		return fmt.Sprintf("CREATE TABLE \"%v\".\"%v\" AS SELECT * FROM \"%v\".\"%v\" WHERE 1=0", s, t, ss, t)
	}
	truncateTableSql = func(s, t string) string {
		return fmt.Sprintf("TRUNCATE TABLE \"%v\".\"%v\"", s, t)
	}
	truncatePartSql = func(s, t, p string) string {
		return fmt.Sprintf("ALTER TABLE \"%v\".\"%v\" TRUNCATE PARTITION \"%v\"", s, t, p)
	}
	analyzeTableSql = func(s, t string) string {
		return fmt.Sprintf("BEGIN \n"+
			"DBMS_STATS.GATHER_TABLE_STATS(\n    "+
			"ownname => '%v',\n    "+
			"tabname => '%v',\n    "+
			"estimate_percent => 100, -- 估算的百分比，100 表示收集所有行\n    "+
			"cascade => TRUE           -- 是否同时收集索引的统计信息\n"+
			");\n"+
			"END;\n"+
			"/", s, t)
	}
	analyzeTableColumnSql = func(s, t string) string {
		return fmt.Sprintf("BEGIN\n    "+
			"DBMS_STATS.GATHER_TABLE_STATS(\n        "+
			"OWNNAME => '%v',\n        "+
			"TABNAME => '%v',\n        "+
			"ESTIMATE_PERCENT => 1.0\n        "+
			"METHOD_OPT => 'FOR ALL COLUMNS SIZE AUTO'\n    "+
			");\n"+
			"END;\n"+
			"/", s, t)
	}
	fullExecCountFuncSql = func(stp, scn, limit, whereSql, whereAdd string) string {
		return fmt.Sprintf("select /*+ parallel(5) */ count(1) as \"tableRows\" from %v %v T where 1=1 %v %v %v", stp, scn, limit, whereSql, whereAdd)
	}
)
